Package Dependencies/ Data
library(sf)
library(ggplot2) #development version!
## devtools::install_github("tidyverse/ggplot2")
library(tidyverse)
library(readr)
library(cowplot)
library(sp)
library(gridExtra)
library(dplyr)
library(ggrepel)
library(plyr)
library(leaflet)
library(rgdal)
library(leaflet)
library(ggmap)
#arrancoordinates <- read.csv("../alldata/ukpostcodes.csv") %>%
# filter(substr(postcode,1,4)=="KA27")
DZBoundaries2016 <- read_sf("../alldata/SG_SIMD_2016")
arran2016 <- DZBoundaries2016[c(4672,4666,4669,4671,4667,4668,4670),]
#Reorder arran 2016
reorderedvector<- c("S01011174", "S01011171", "S01011177", "S01011176", "S01011175", "S01011173", "S01011172" )
arran2016 <- arran2016 %>%
slice(match(reorderedvector, DataZone))
simple.sf <- st_as_sf(arrancoordinates, coords=c('longitude','latitude'))
st_crs(simple.sf) <- 4326
exampleshapes <- sf:::as_Spatial(arran2016$geometry)
examplepoints <- sf:::as_Spatial(simple.sf$geom)
examplepoints <- spTransform(examplepoints, CRS("+proj=longlat +datum=WGS84"))
exampleshapes <- spTransform(exampleshapes, CRS("+proj=longlat +datum=WGS84"))
namingdzpostcode <- over(exampleshapes, examplepoints, returnList = TRUE)
listID <- list(1,2,3,4,5,6,7)
function100 <- function(argument)
{
argument <- arrancoordinates[namingdzpostcode[[argument]],] %>% mutate(DataZone=argument)
}
newarrancoordinates <- lapply(1:7,function100)
newarrancoordinates <- rbind(newarrancoordinates[[1]], newarrancoordinates[[2]], newarrancoordinates[[3]], newarrancoordinates[[4]], newarrancoordinates[[5]], newarrancoordinates[[6]], newarrancoordinates[[7]])
newarrancoordinates$listID <- revalue(as.character(newarrancoordinates$DataZone),
c('1'="S01004409/S01011174", '2'="S01004372/S01011171", '3'="S01004353/S01011177", '4'="S01004352/S01011176", '5'="S01004351/S01011175", '6'="S01004350/S01011173", '7'="S01004349/S01011172"))
///
Coordinates
postcodelist <- paste(unique(newarrancoordinates$listID), "Postcodes", sep=" ")
datazonelist <- paste(unique(newarrancoordinates$listID), "Datazones", sep=" ")
m = leaflet() %>% addTiles()
m %>% setView(-5.227680, 55.582338, zoom = 10) %>%
#allcoordinates
addMarkers(
lng = newarrancoordinates$longitude, lat = newarrancoordinates$latitude,
label = newarrancoordinates$postcode,
labelOptions = labelOptions(noHide = F), group = "Postcode Plots") %>%
hideGroup("All Postcode Plots") %>%
#alldatazones
addPolygons(data=exampleshapes,
weight = 2,
label = datazonelist,
group = "All Datazones") %>%
hideGroup("Datazones") %>%
#selectcoordinates
addMarkers(
lng = newarrancoordinates$longitude, lat = newarrancoordinates$latitude,
label = newarrancoordinates$postcode,
labelOptions = labelOptions(noHide = F), group = newarrancoordinates$listID) %>%
hideGroup(newarrancoordinates$listID) %>%
#selectdatazone
addPolygons(data = exampleshapes[1] ,
weight = 2, label = datazonelist[1], group = datazonelist[1]) %>%
addPolygons(data = exampleshapes[2] ,
weight = 2, label = datazonelist[2], group = datazonelist[2]) %>%
addPolygons(data = exampleshapes[3] ,
weight = 2, label = datazonelist[3], group = datazonelist[3]) %>%
addPolygons(data = exampleshapes[4] ,
weight = 2, label = datazonelist[4], group = datazonelist[4]) %>%
addPolygons(data = exampleshapes[5] ,
weight = 2, label = datazonelist[5], group = datazonelist[5]) %>%
addPolygons(data = exampleshapes[6] ,
weight = 2, label = datazonelist[6], group = datazonelist[6]) %>%
addPolygons(data = exampleshapes[7] ,
weight = 2, label = datazonelist[7], group = datazonelist[7]) %>%
hideGroup(datazonelist[1]) %>%
hideGroup(datazonelist[2]) %>%
hideGroup(datazonelist[3]) %>%
hideGroup(datazonelist[4]) %>%
hideGroup(datazonelist[5]) %>%
hideGroup(datazonelist[6]) %>%
hideGroup(datazonelist[7]) %>%
#Layers control
addLayersControl(
baseGroups = c("All Datazones", "Postcode Plots", "Nothing"),
overlayGroups = c(newarrancoordinates$listID, datazonelist),
options = layersControlOptions(collapsed = TRUE)
)
Inputing example markers.
cliniccoordinates <- read.csv("../alldata/clinics.csv") %>%
dplyr::left_join(arrancoordinates, by="postcode")
Column `postcode` joining factors with different levels, coercing to character vector
#change to character
cliniccoordinates$X <- as.character(cliniccoordinates$X)
m %>% setView(-5.227680, 55.582338, zoom = 10) %>%
#allcoordinates
addMarkers(
lng = newarrancoordinates$longitude, lat = newarrancoordinates$latitude,
label = newarrancoordinates$postcode,
labelOptions = labelOptions(noHide = F), group = "All Postcode Plots") %>%
hideGroup("All Postcode Plots") %>%
#alldatazones
addPolygons(data=exampleshapes,
weight = 2,
label = datazonelist,
group = "All Datazones",
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("All Datazones") %>%
#selectcoordinates
addMarkers(
lng = newarrancoordinates$longitude, lat = newarrancoordinates$latitude,
label = newarrancoordinates$postcode,
labelOptions = labelOptions(noHide = F), group = newarrancoordinates$listID) %>%
hideGroup(newarrancoordinates$listID) %>%
#selectdatazone
addPolygons(data = exampleshapes[1] ,
weight = 2, label = datazonelist[1], group = datazonelist[1]) %>%
addPolygons(data = exampleshapes[2] ,
weight = 2, label = datazonelist[2], group = datazonelist[2]) %>%
addPolygons(data = exampleshapes[3] ,
weight = 2, label = datazonelist[3], group = datazonelist[3]) %>%
addPolygons(data = exampleshapes[4] ,
weight = 2, label = datazonelist[4], group = datazonelist[4]) %>%
addPolygons(data = exampleshapes[5] ,
weight = 2, label = datazonelist[5], group = datazonelist[5]) %>%
addPolygons(data = exampleshapes[6] ,
weight = 2, label = datazonelist[6], group = datazonelist[6]) %>%
addPolygons(data = exampleshapes[7] ,
weight = 2, label = datazonelist[7], group = datazonelist[7]) %>%
hideGroup(datazonelist[1]) %>%
hideGroup(datazonelist[2]) %>%
hideGroup(datazonelist[3]) %>%
hideGroup(datazonelist[4]) %>%
hideGroup(datazonelist[5]) %>%
hideGroup(datazonelist[6]) %>%
hideGroup(datazonelist[7]) %>%
#cliniccoordinates
addMarkers(
lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
label = cliniccoordinates$X,
labelOptions = labelOptions(noHide = F), group = "All GP clinics") %>%
hideGroup("All GP clinics") %>%
#cliniccoordinates
addMarkers(
lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
label = cliniccoordinates$X,
labelOptions = labelOptions(noHide = F), group = cliniccoordinates$X) %>%
hideGroup(cliniccoordinates$X) %>%
#Layers control
addLayersControl(
baseGroups = c("All Datazones", "All Postcode Plots", "All GP clinics", "Nothing"),
overlayGroups = c(newarrancoordinates$listID, datazonelist, cliniccoordinates$X),
options = layersControlOptions(collapsed = TRUE)
)
pal <- colorNumeric(
palette = "Blues",
domain = exampleshapes2$Percentile)
leaflet() %>%
addTiles() %>%
setView(-5.227680, 55.582338, zoom = 10) %>%
#alldatazones
addPolygons(data=exampleshapes,
weight = 2,
label = datazonelist,
group = "2004",
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2004") %>%
addPolygons(data=exampleshapes,
weight = 2,
label = datazonelist,
group = "2006",
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2006") %>%
addPolygons(data=exampleshapes,
weight = 2,
label = datazonelist,
group = "2009",
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2009") %>%
addPolygons(data=exampleshapes,
weight = 2,
label = datazonelist,
group = "2012",
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2012") %>%
addPolygons(data=exampleshapes2,
weight = 2,
label = datazonelist,
group = "2016",
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2016") %>%
#cliniccoordinates
addMarkers(
lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
label = cliniccoordinates$X,
labelOptions = labelOptions(noHide = F), group = cliniccoordinates$X) %>%
hideGroup(cliniccoordinates$X) %>%
#Layers control
addLayersControl(
baseGroups = c("2004", "2006", "2009", "2012", "2016", "Nothing"),
overlayGroups = c(cliniccoordinates$X),
options = layersControlOptions(collapsed = TRUE)
)
exampleshapes2 <- as(arran2016, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))
pal <- colorNumeric(
palette = "Blues",
domain = exampleshapes2$Percentile)
leaflet() %>%
addTiles() %>%
setView(-5.227680, 55.582338, zoom = 10) %>%
addPolygons(data = exampleshapes2,
weight = 2,
label = datazonelist,
group = "2016",
fillOpacity =0.8,
color = ~pal(exampleshapes2$Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE))
exampleshapes3 <- as(arransimd, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))
pal2 <- colorNumeric(
palette = "Blues",
domain = exampleshapes3$Percentile)
#exampleshapes3$year=2016
#exampleshapes3[exampleshapes3$year == 2016, ]
leaflet() %>%
addTiles() %>%
setView(-5.227680, 55.582338, zoom = 10) %>%
addPolygons(data = exampleshapes3[exampleshapes3$year == 2016, ],
weight = 2,
label = datazonelist,
group = "2016",
fillOpacity =0.8,
color = ~pal2(exampleshapes3$Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE))
arransimd$listID <- revalue(arransimd$DataZone,
c("S01004409"="S01004409/S01011174", "S01004372"="S01004372/S01011171", "S01004353"="S01004353/S01011177", "S01004352"="S01004352/S01011176", "S01004351"="S01004351/S01011175", "S01004350"="S01004350/S01011173", "S01004349"="S01004349/S01011172", "S01011174"="S01004409/S01011174", "S01011171"="S01004372/S01011171", "S01011177"="S01004353/S01011177", "S01011176"="S01004352/S01011176", "S01011175"="S01004351/S01011175", "S01011173"="S01004350/S01011173", "S01011172"="S01004349/S01011172"))
#Check you have updated arransimd
exampleshapes3 <- as(arransimd, "Spatial") %>%
spTransform(CRS("+proj=longlat +datum=WGS84"))
pal2 <- colorNumeric(
palette = "viridis",
domain = exampleshapes3$Percentile)
#exampleshapes3
listlistlist <- paste(datazonelist, exampleshapes3$Percentile, sep=" ") %>%
paste("%", sep="")
leaflet() %>%
addTiles() %>%
setView(-5.227680, 55.582338, zoom = 10) %>%
#alldatazones
addPolygons(data=exampleshapes3[exampleshapes3$year == 2004, ],
weight = 2,
label = listlistlist[29:35],
group = "2004",
fillOpacity =0.8,
color = ~pal2(Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2004") %>%
addPolygons(data=exampleshapes3[exampleshapes3$year == 2006, ],
weight = 2,
label = listlistlist[22:28],
group = "2006",
fillOpacity =0.8,
color = ~pal2(Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2006") %>%
addPolygons(data=exampleshapes3[exampleshapes3$year == 2009, ],
weight = 2,
label = listlistlist[15:21],
group = "2009",
fillOpacity =0.8,
color = ~pal2(Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2009") %>%
addPolygons(data=exampleshapes3[exampleshapes3$year == 2012, ],
weight = 2,
label = listlistlist[8:14],
group = "2012",
fillOpacity =0.8,
color = ~pal2(Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2012") %>%
addPolygons(data=exampleshapes3[exampleshapes3$year == 2016, ],
weight = 2,
label = listlistlist[1:7],
group = "2016",
fillOpacity =0.8,
color = ~pal2(Percentile),
highlightOptions = highlightOptions(color = "black", weight = 2,
bringToFront = TRUE)) %>%
hideGroup("2016") %>%
#cliniccoordinates
addMarkers(
lng = cliniccoordinates$longitude, lat = cliniccoordinates$latitude,
label = cliniccoordinates$X,
labelOptions = labelOptions(noHide = F), group = cliniccoordinates$X) %>%
hideGroup(cliniccoordinates$X) %>%
addLegend("bottomleft", pal = pal2, values = exampleshapes3$Percentile,
title = "SIMD Percentile",
labFormat = labelFormat(suffix = "%"),
opacity = 1
) %>%
#Layers control
addLayersControl(
baseGroups = c("2004", "2006", "2009", "2012", "2016", "Nothing"),
overlayGroups = c(cliniccoordinates$X),
options = layersControlOptions(collapsed = TRUE)
)
listlistlist
[1] "S01004409/S01011174 Datazones 71%" "S01004372/S01011171 Datazones 58%"
[3] "S01004353/S01011177 Datazones 50%" "S01004352/S01011176 Datazones 79%"
[5] "S01004351/S01011175 Datazones 56%" "S01004350/S01011173 Datazones 78%"
[7] "S01004349/S01011172 Datazones 52%" "S01004409/S01011174 Datazones 64%"
[9] "S01004372/S01011171 Datazones 66%" "S01004353/S01011177 Datazones 78%"
[11] "S01004352/S01011176 Datazones 76%" "S01004351/S01011175 Datazones 52%"
[13] "S01004350/S01011173 Datazones 67%" "S01004349/S01011172 Datazones 50%"
[15] "S01004409/S01011174 Datazones 60%" "S01004372/S01011171 Datazones 63%"
[17] "S01004353/S01011177 Datazones 68%" "S01004352/S01011176 Datazones 63%"
[19] "S01004351/S01011175 Datazones 51%" "S01004350/S01011173 Datazones 61%"
[21] "S01004349/S01011172 Datazones 48%" "S01004409/S01011174 Datazones 59%"
[23] "S01004372/S01011171 Datazones 61%" "S01004353/S01011177 Datazones 71%"
[25] "S01004352/S01011176 Datazones 65%" "S01004351/S01011175 Datazones 51%"
[27] "S01004350/S01011173 Datazones 61%" "S01004349/S01011172 Datazones 54%"
[29] "S01004409/S01011174 Datazones 44%" "S01004372/S01011171 Datazones 56%"
[31] "S01004353/S01011177 Datazones 65%" "S01004352/S01011176 Datazones 63%"
[33] "S01004351/S01011175 Datazones 47%" "S01004350/S01011173 Datazones 61%"
[35] "S01004349/S01011172 Datazones 53%"
Trying to make a chloropleth.
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100) pal <- colorBin(“YlOrRd”, domain = arransimd$Percentile, bins = bins)
arransimd10 <-arransimd st_crs(arransimd10) <- “+proj=longlat +datum=WGS84”
arransimd10 %>% st_set_crs(“+proj=longlat +datum=WGS84”)
addpolygonsarran2016 <- arransimd10 %>% filter(year == 2016, DataZone == “S01011177”)
m %>% setView(-5.227680, 55.582338, zoom = 10) %>% addPolygons(data = addpolygonsarran2016$geometry, weight = 2) %>%
m %>% setView(-5.227680, 55.582338, zoom = 10) %>% addPolygons(data = arransimd10, weight = 2) %>%
addLayersControl( overlayGroups = c(datazonelist, datazonelist[3]), options = layersControlOptions(collapsed = TRUE) )
leaflet() %>% addTiles() %>% addPolygons(filter(arransimd10$geom, DataZone == “S01011177”)) setView(-5.227680, 55.582338, zoom = 10)
addPolygons(data = exampleshapes[1] , weight = 2, label = datazonelist[1], group = datazonelist[1]) %>% addPolygons(data = exampleshapes[2] , weight = 2, label = datazonelist[2], group = datazonelist[2]) %>% addPolygons(data = exampleshapes[3] , weight = 2, label = datazonelist[3], group = datazonelist[3]) %>% addPolygons(data = exampleshapes[4] , weight = 2, label = datazonelist[4], group = datazonelist[4]) %>% addPolygons(data = exampleshapes[5] , weight = 2, label = datazonelist[5], group = datazonelist[5]) %>% addPolygons(data = exampleshapes[6] , weight = 2, label = datazonelist[6], group = datazonelist[6]) %>% addPolygons(data = exampleshapes[7] , weight = 2, label = datazonelist[7], group = datazonelist[7]) %>% hideGroup(datazonelist[1]) %>% hideGroup(datazonelist[2]) %>% hideGroup(datazonelist[3]) %>% hideGroup(datazonelist[4]) %>% hideGroup(datazonelist[5]) %>% hideGroup(datazonelist[6]) %>% hideGroup(datazonelist[7]) %>%
install.packages(“geojsonio”) library(“geojsonio”)
arranDZleaflet <-geojsonio::geojson_read(“../alldata/SG_SIMD_2016/SG_SIMD_2016.shp”, what = “sp”)
leaflet() %>% setView(-5.227680, 55.582338, zoom = 10) %>% addTiles() %>% addPolygons(data = arranDZleaflet, weight = 2)
addPolygons(data = arranDZleaflet, weight = 2, label = arranDZleaflet, group = arranDZleaflet) %>% hideGroup(arranDZleaflet) %>% addLayersControl( baseGroups = c(arranDZleaflet), overlayGroups = c(arranDZleaflet), options = layersControlOptions(collapsed = TRUE) )
LS0tCnRpdGxlOiAiTWFwcGluZyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKI1BhY2thZ2UgRGVwZW5kZW5jaWVzLyBEYXRhCmBgYHtyfQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KGdncGxvdDIpICNkZXZlbG9wbWVudCB2ZXJzaW9uIQojIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInRpZHl2ZXJzZS9nZ3Bsb3QyIikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShzcCkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShwbHlyKQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkocmdkYWwpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShnZ21hcCkKYGBgCgpgYGB7cn0KYXJyYW5jb29yZGluYXRlcyA8LSByZWFkLmNzdigiLi4vYWxsZGF0YS91a3Bvc3Rjb2Rlcy5jc3YiKSAlPiUKIGZpbHRlcihzdWJzdHIocG9zdGNvZGUsMSw0KT09IktBMjciKQpgYGAKCmBgYHtyfQpEWkJvdW5kYXJpZXMyMDE2IDwtIHJlYWRfc2YoIi4uL2FsbGRhdGEvU0dfU0lNRF8yMDE2IikKYGBgCgpgYGB7cn0KYXJyYW4yMDE2IDwtIERaQm91bmRhcmllczIwMTZbYyg0NjcyLDQ2NjYsNDY2OSw0NjcxLDQ2NjcsNDY2OCw0NjcwKSxdCiNSZW9yZGVyIGFycmFuIDIwMTYKcmVvcmRlcmVkdmVjdG9yPC0gYygiUzAxMDExMTc0IiwgIlMwMTAxMTE3MSIsICJTMDEwMTExNzciLCAiUzAxMDExMTc2IiwgIlMwMTAxMTE3NSIsICJTMDEwMTExNzMiLCAiUzAxMDExMTcyIiApCmFycmFuMjAxNiA8LSBhcnJhbjIwMTYgJT4lCiAgc2xpY2UobWF0Y2gocmVvcmRlcmVkdmVjdG9yLCBEYXRhWm9uZSkpCmBgYAoKYGBge3J9CnNpbXBsZS5zZiA8LSBzdF9hc19zZihhcnJhbmNvb3JkaW5hdGVzLCBjb29yZHM9YygnbG9uZ2l0dWRlJywnbGF0aXR1ZGUnKSkKc3RfY3JzKHNpbXBsZS5zZikgPC0gNDMyNgoKZXhhbXBsZXNoYXBlcyA8LSBzZjo6OmFzX1NwYXRpYWwoYXJyYW4yMDE2JGdlb21ldHJ5KQpleGFtcGxlcG9pbnRzIDwtIHNmOjo6YXNfU3BhdGlhbChzaW1wbGUuc2YkZ2VvbSkKCmV4YW1wbGVwb2ludHMgPC0gc3BUcmFuc2Zvcm0oZXhhbXBsZXBvaW50cywgQ1JTKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCIpKQpleGFtcGxlc2hhcGVzIDwtIHNwVHJhbnNmb3JtKGV4YW1wbGVzaGFwZXMsIENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKCm5hbWluZ2R6cG9zdGNvZGUgPC0gb3ZlcihleGFtcGxlc2hhcGVzLCBleGFtcGxlcG9pbnRzLCByZXR1cm5MaXN0ID0gVFJVRSkKYGBgCgpgYGB7cn0KbGlzdElEIDwtIGxpc3QoMSwyLDMsNCw1LDYsNykKCmZ1bmN0aW9uMTAwIDwtIGZ1bmN0aW9uKGFyZ3VtZW50KSAKewogIGFyZ3VtZW50IDwtIGFycmFuY29vcmRpbmF0ZXNbbmFtaW5nZHpwb3N0Y29kZVtbYXJndW1lbnRdXSxdICU+JSBtdXRhdGUoRGF0YVpvbmU9YXJndW1lbnQpCn0KCm5ld2FycmFuY29vcmRpbmF0ZXMgPC0gbGFwcGx5KDE6NyxmdW5jdGlvbjEwMCkKbmV3YXJyYW5jb29yZGluYXRlcyA8LSByYmluZChuZXdhcnJhbmNvb3JkaW5hdGVzW1sxXV0sIG5ld2FycmFuY29vcmRpbmF0ZXNbWzJdXSwgbmV3YXJyYW5jb29yZGluYXRlc1tbM11dLCBuZXdhcnJhbmNvb3JkaW5hdGVzW1s0XV0sIG5ld2FycmFuY29vcmRpbmF0ZXNbWzVdXSwgbmV3YXJyYW5jb29yZGluYXRlc1tbNl1dLCBuZXdhcnJhbmNvb3JkaW5hdGVzW1s3XV0pCgpuZXdhcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCA8LSByZXZhbHVlKGFzLmNoYXJhY3RlcihuZXdhcnJhbmNvb3JkaW5hdGVzJERhdGFab25lKSwKICAgICAgICAgICAgICAgYygnMSc9IlMwMTAwNDQwOS9TMDEwMTExNzQiLCAnMic9IlMwMTAwNDM3Mi9TMDEwMTExNzEiLCAnMyc9IlMwMTAwNDM1My9TMDEwMTExNzciLCAnNCc9IlMwMTAwNDM1Mi9TMDEwMTExNzYiLCAnNSc9IlMwMTAwNDM1MS9TMDEwMTExNzUiLCAnNic9IlMwMTAwNDM1MC9TMDEwMTExNzMiLCAnNyc9IlMwMTAwNDM0OS9TMDEwMTExNzIiKSkKYGBgCgovLy8KCiNDb29yZGluYXRlcwoKYGBge3J9CnBvc3Rjb2RlbGlzdCA8LSBwYXN0ZSh1bmlxdWUobmV3YXJyYW5jb29yZGluYXRlcyRsaXN0SUQpLCAiUG9zdGNvZGVzIiwgc2VwPSIgIikKZGF0YXpvbmVsaXN0IDwtIHBhc3RlKHVuaXF1ZShuZXdhcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCksICJEYXRhem9uZXMiLCBzZXA9IiAiKQoKbSA9IGxlYWZsZXQoKSAlPiUgYWRkVGlsZXMoKQpgYGAKCmBgYHtyfQptICU+JSBzZXRWaWV3KC01LjIyNzY4MCwgNTUuNTgyMzM4LCB6b29tID0gMTApICU+JSAKCiNhbGxjb29yZGluYXRlcwphZGRNYXJrZXJzKAogICAgbG5nID0gbmV3YXJyYW5jb29yZGluYXRlcyRsb25naXR1ZGUsIGxhdCA9IG5ld2FycmFuY29vcmRpbmF0ZXMkbGF0aXR1ZGUsCiAgICBsYWJlbCA9IG5ld2FycmFuY29vcmRpbmF0ZXMkcG9zdGNvZGUsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMobm9IaWRlID0gRiksIGdyb3VwID0gIlBvc3Rjb2RlIFBsb3RzIikgJT4lCmhpZGVHcm91cCgiQWxsIFBvc3Rjb2RlIFBsb3RzIikgJT4lIAoKI2FsbGRhdGF6b25lcyAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlcywgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGRhdGF6b25lbGlzdCwKICAgICAgICAgICAgZ3JvdXAgPSAiQWxsIERhdGF6b25lcyIpICU+JSAKaGlkZUdyb3VwKCJEYXRhem9uZXMiKSAlPiUgCiAgCiNzZWxlY3Rjb29yZGluYXRlcwphZGRNYXJrZXJzKAogICAgbG5nID0gbmV3YXJyYW5jb29yZGluYXRlcyRsb25naXR1ZGUsIGxhdCA9IG5ld2FycmFuY29vcmRpbmF0ZXMkbGF0aXR1ZGUsCiAgICBsYWJlbCA9IG5ld2FycmFuY29vcmRpbmF0ZXMkcG9zdGNvZGUsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMobm9IaWRlID0gRiksIGdyb3VwID0gbmV3YXJyYW5jb29yZGluYXRlcyRsaXN0SUQpICU+JSAKaGlkZUdyb3VwKG5ld2FycmFuY29vcmRpbmF0ZXMkbGlzdElEKSAlPiUgCgojc2VsZWN0ZGF0YXpvbmUKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbMV0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbMV0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzFdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzJdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzJdLCBncm91cCA9IGRhdGF6b25lbGlzdFsyXSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1szXSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFszXSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbM10pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbNF0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbNF0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzRdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzVdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzVdLCBncm91cCA9IGRhdGF6b25lbGlzdFs1XSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1s2XSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFs2XSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbNl0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbN10gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbN10sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzddKSAlPiUgCmhpZGVHcm91cChkYXRhem9uZWxpc3RbMV0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzJdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFszXSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbNF0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzVdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFs2XSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbN10pICU+JQoKI0xheWVycyBjb250cm9sCmFkZExheWVyc0NvbnRyb2woCiAgICBiYXNlR3JvdXBzID0gYygiQWxsIERhdGF6b25lcyIsICJQb3N0Y29kZSBQbG90cyIsICJOb3RoaW5nIiksCiAgICBvdmVybGF5R3JvdXBzID0gYyhuZXdhcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCwgZGF0YXpvbmVsaXN0KSwKICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBUUlVFKQogICkKYGBgCgpJbnB1dGluZyBleGFtcGxlIG1hcmtlcnMuCmBgYHtyfQpjbGluaWNjb29yZGluYXRlcyA8LSByZWFkLmNzdigiLi4vYWxsZGF0YS9jbGluaWNzLmNzdiIpICU+JQpkcGx5cjo6bGVmdF9qb2luKGFycmFuY29vcmRpbmF0ZXMsIGJ5PSJwb3N0Y29kZSIpCiNjaGFuZ2UgdG8gY2hhcmFjdGVyCmNsaW5pY2Nvb3JkaW5hdGVzJFggPC0gYXMuY2hhcmFjdGVyKGNsaW5pY2Nvb3JkaW5hdGVzJFgpCmBgYAoKYGBge3J9Cm0gJT4lIHNldFZpZXcoLTUuMjI3NjgwLCA1NS41ODIzMzgsIHpvb20gPSAxMCkgJT4lIAoKI2FsbGNvb3JkaW5hdGVzCmFkZE1hcmtlcnMoCiAgICBsbmcgPSBuZXdhcnJhbmNvb3JkaW5hdGVzJGxvbmdpdHVkZSwgbGF0ID0gbmV3YXJyYW5jb29yZGluYXRlcyRsYXRpdHVkZSwKICAgIGxhYmVsID0gbmV3YXJyYW5jb29yZGluYXRlcyRwb3N0Y29kZSwKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBGKSwgZ3JvdXAgPSAiQWxsIFBvc3Rjb2RlIFBsb3RzIikgJT4lCmhpZGVHcm91cCgiQWxsIFBvc3Rjb2RlIFBsb3RzIikgJT4lIAoKI2FsbGRhdGF6b25lcyAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlcywgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGRhdGF6b25lbGlzdCwKICAgICAgICAgICAgZ3JvdXAgPSAiQWxsIERhdGF6b25lcyIsCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCJBbGwgRGF0YXpvbmVzIikgJT4lIAogIAojc2VsZWN0Y29vcmRpbmF0ZXMKYWRkTWFya2VycygKICAgIGxuZyA9IG5ld2FycmFuY29vcmRpbmF0ZXMkbG9uZ2l0dWRlLCBsYXQgPSBuZXdhcnJhbmNvb3JkaW5hdGVzJGxhdGl0dWRlLAogICAgbGFiZWwgPSBuZXdhcnJhbmNvb3JkaW5hdGVzJHBvc3Rjb2RlLAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IEYpLCBncm91cCA9IG5ld2FycmFuY29vcmRpbmF0ZXMkbGlzdElEKSAlPiUgCmhpZGVHcm91cChuZXdhcnJhbmNvb3JkaW5hdGVzJGxpc3RJRCkgJT4lIAoKI3NlbGVjdGRhdGF6b25lCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzFdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzFdLCBncm91cCA9IGRhdGF6b25lbGlzdFsxXSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1syXSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFsyXSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbMl0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbM10gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbM10sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzNdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzRdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzRdLCBncm91cCA9IGRhdGF6b25lbGlzdFs0XSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1s1XSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFs1XSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbNV0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbNl0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbNl0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzZdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzddICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzddLCBncm91cCA9IGRhdGF6b25lbGlzdFs3XSkgJT4lIApoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzFdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFsyXSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbM10pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzRdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFs1XSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbNl0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzddKSAlPiUKICAKI2NsaW5pY2Nvb3JkaW5hdGVzCmFkZE1hcmtlcnMoCiAgICBsbmcgPSBjbGluaWNjb29yZGluYXRlcyRsb25naXR1ZGUsIGxhdCA9IGNsaW5pY2Nvb3JkaW5hdGVzJGxhdGl0dWRlLAogICAgbGFiZWwgPSBjbGluaWNjb29yZGluYXRlcyRYLAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKG5vSGlkZSA9IEYpLCBncm91cCA9ICJBbGwgR1AgY2xpbmljcyIpICU+JQogIGhpZGVHcm91cCgiQWxsIEdQIGNsaW5pY3MiKSAlPiUgICAKCiNjbGluaWNjb29yZGluYXRlcwphZGRNYXJrZXJzKAogICAgbG5nID0gY2xpbmljY29vcmRpbmF0ZXMkbG9uZ2l0dWRlLCBsYXQgPSBjbGluaWNjb29yZGluYXRlcyRsYXRpdHVkZSwKICAgIGxhYmVsID0gY2xpbmljY29vcmRpbmF0ZXMkWCwKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhub0hpZGUgPSBGKSwgZ3JvdXAgPSBjbGluaWNjb29yZGluYXRlcyRYKSAlPiUKICBoaWRlR3JvdXAoY2xpbmljY29vcmRpbmF0ZXMkWCkgJT4lICAgCiAgCiNMYXllcnMgY29udHJvbAphZGRMYXllcnNDb250cm9sKAogICAgYmFzZUdyb3VwcyA9IGMoIkFsbCBEYXRhem9uZXMiLCAiQWxsIFBvc3Rjb2RlIFBsb3RzIiwgIkFsbCBHUCBjbGluaWNzIiwgIk5vdGhpbmciKSwKICAgIG92ZXJsYXlHcm91cHMgPSBjKG5ld2FycmFuY29vcmRpbmF0ZXMkbGlzdElELCBkYXRhem9uZWxpc3QsIGNsaW5pY2Nvb3JkaW5hdGVzJFgpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpCiAgKQpgYGAKCmBgYHtyfQpwYWwgPC0gY29sb3JOdW1lcmljKAogIHBhbGV0dGUgPSAiQmx1ZXMiLAogIGRvbWFpbiA9IGV4YW1wbGVzaGFwZXMyJFBlcmNlbnRpbGUpCgpsZWFmbGV0KCkgJT4lIAogIGFkZFRpbGVzKCkgJT4lIAogIHNldFZpZXcoLTUuMjI3NjgwLCA1NS41ODIzMzgsIHpvb20gPSAxMCkgJT4lIAoKI2FsbGRhdGF6b25lcyAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlcywgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGRhdGF6b25lbGlzdCwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAwNCIsCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDA0IikgJT4lIAogIAphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgbGFiZWwgPSBkYXRhem9uZWxpc3QsCiAgICAgICAgICAgIGdyb3VwID0gIjIwMDYiLAogICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJibGFjayIsIHdlaWdodCA9IDIsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpKSAlPiUgCmhpZGVHcm91cCgiMjAwNiIpICU+JSAKICAKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gZGF0YXpvbmVsaXN0LAogICAgICAgICAgICBncm91cCA9ICIyMDA5IiwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMDkiKSAlPiUgCiAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlcywgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGRhdGF6b25lbGlzdCwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAxMiIsCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDEyIikgJT4lIAoKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzMiwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGRhdGF6b25lbGlzdCwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAxNiIsCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDE2IikgJT4lIAogIAojY2xpbmljY29vcmRpbmF0ZXMKYWRkTWFya2VycygKICAgIGxuZyA9IGNsaW5pY2Nvb3JkaW5hdGVzJGxvbmdpdHVkZSwgbGF0ID0gY2xpbmljY29vcmRpbmF0ZXMkbGF0aXR1ZGUsCiAgICBsYWJlbCA9IGNsaW5pY2Nvb3JkaW5hdGVzJFgsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMobm9IaWRlID0gRiksIGdyb3VwID0gY2xpbmljY29vcmRpbmF0ZXMkWCkgJT4lCiAgaGlkZUdyb3VwKGNsaW5pY2Nvb3JkaW5hdGVzJFgpICU+JSAgIAogIAojTGF5ZXJzIGNvbnRyb2wKYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCIyMDA0IiwgIjIwMDYiLCAiMjAwOSIsICIyMDEyIiwgIjIwMTYiLCAiTm90aGluZyIpLAogICAgb3ZlcmxheUdyb3VwcyA9IGMoY2xpbmljY29vcmRpbmF0ZXMkWCksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApCmBgYAoKYGBge3J9CmV4YW1wbGVzaGFwZXMyIDwtIGFzKGFycmFuMjAxNiwgIlNwYXRpYWwiKSAlPiUKc3BUcmFuc2Zvcm0oQ1JTKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCIpKQoKcGFsIDwtIGNvbG9yTnVtZXJpYygKICBwYWxldHRlID0gIkJsdWVzIiwKICBkb21haW4gPSBleGFtcGxlc2hhcGVzMiRQZXJjZW50aWxlKQoKbGVhZmxldCgpICU+JSAKICBhZGRUaWxlcygpICU+JSAKICBzZXRWaWV3KC01LjIyNzY4MCwgNTUuNTgyMzM4LCB6b29tID0gMTApICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXMyLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gZGF0YXpvbmVsaXN0LAogICAgICAgICAgICBncm91cCA9ICIyMDE2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsKGV4YW1wbGVzaGFwZXMyJFBlcmNlbnRpbGUpLAogICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJibGFjayIsIHdlaWdodCA9IDIsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpKQoKYGBgCgpgYGB7cn0KZXhhbXBsZXNoYXBlczMgPC0gYXMoYXJyYW5zaW1kLCAiU3BhdGlhbCIpICU+JQpzcFRyYW5zZm9ybShDUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikpCgpwYWwyIDwtIGNvbG9yTnVtZXJpYygKICBwYWxldHRlID0gIkJsdWVzIiwKICBkb21haW4gPSBleGFtcGxlc2hhcGVzMyRQZXJjZW50aWxlKQoKI2V4YW1wbGVzaGFwZXMzJHllYXI9MjAxNgoKI2V4YW1wbGVzaGFwZXMzW2V4YW1wbGVzaGFwZXMzJHllYXIgPT0gMjAxNiwgXQogIApsZWFmbGV0KCkgJT4lIAogIGFkZFRpbGVzKCkgJT4lIAogIHNldFZpZXcoLTUuMjI3NjgwLCA1NS41ODIzMzgsIHpvb20gPSAxMCkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlczNbZXhhbXBsZXNoYXBlczMkeWVhciA9PSAyMDE2LCBdLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gZGF0YXpvbmVsaXN0LAogICAgICAgICAgICBncm91cCA9ICIyMDE2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihleGFtcGxlc2hhcGVzMyRQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkKCmBgYAoKYGBge3J9CmFycmFuc2ltZCRsaXN0SUQgPC0gcmV2YWx1ZShhcnJhbnNpbWQkRGF0YVpvbmUsCiAgICAgICAgICAgICAgIGMoIlMwMTAwNDQwOSI9IlMwMTAwNDQwOS9TMDEwMTExNzQiLCAiUzAxMDA0MzcyIj0iUzAxMDA0MzcyL1MwMTAxMTE3MSIsICJTMDEwMDQzNTMiPSJTMDEwMDQzNTMvUzAxMDExMTc3IiwgIlMwMTAwNDM1MiI9IlMwMTAwNDM1Mi9TMDEwMTExNzYiLCAiUzAxMDA0MzUxIj0iUzAxMDA0MzUxL1MwMTAxMTE3NSIsICJTMDEwMDQzNTAiPSJTMDEwMDQzNTAvUzAxMDExMTczIiwgIlMwMTAwNDM0OSI9IlMwMTAwNDM0OS9TMDEwMTExNzIiLCAiUzAxMDExMTc0Ij0iUzAxMDA0NDA5L1MwMTAxMTE3NCIsICJTMDEwMTExNzEiPSJTMDEwMDQzNzIvUzAxMDExMTcxIiwgIlMwMTAxMTE3NyI9IlMwMTAwNDM1My9TMDEwMTExNzciLCAiUzAxMDExMTc2Ij0iUzAxMDA0MzUyL1MwMTAxMTE3NiIsICJTMDEwMTExNzUiPSJTMDEwMDQzNTEvUzAxMDExMTc1IiwgIlMwMTAxMTE3MyI9IlMwMTAwNDM1MC9TMDEwMTExNzMiLCAiUzAxMDExMTcyIj0iUzAxMDA0MzQ5L1MwMTAxMTE3MiIpKQoKI0NoZWNrIHlvdSBoYXZlIHVwZGF0ZWQgYXJyYW5zaW1kCgpleGFtcGxlc2hhcGVzMyA8LSBhcyhhcnJhbnNpbWQsICJTcGF0aWFsIikgJT4lCnNwVHJhbnNmb3JtKENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkKCnBhbDIgPC0gY29sb3JOdW1lcmljKAogIHBhbGV0dGUgPSAidmlyaWRpcyIsCiAgZG9tYWluID0gZXhhbXBsZXNoYXBlczMkUGVyY2VudGlsZSkKCiNleGFtcGxlc2hhcGVzMwoKbGlzdGxpc3RsaXN0IDwtIHBhc3RlKGRhdGF6b25lbGlzdCwgZXhhbXBsZXNoYXBlczMkUGVyY2VudGlsZSwgc2VwPSIgIikgJT4lCnBhc3RlKCIlIiwgc2VwPSIiKQoKbGVhZmxldCgpICU+JSAKICBhZGRUaWxlcygpICU+JSAKICBzZXRWaWV3KC01LjIyNzY4MCwgNTUuNTgyMzM4LCB6b29tID0gMTApICU+JSAKCiNhbGxkYXRhem9uZXMgIAphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMzW2V4YW1wbGVzaGFwZXMzJHllYXIgPT0gMjAwNCwgXSwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGxpc3RsaXN0bGlzdFsyOTozNV0sCiAgICAgICAgICAgIGdyb3VwID0gIjIwMDQiLAogICAgICAgICAgICBmaWxsT3BhY2l0eSA9MC44LAogICAgICAgICAgICBjb2xvciA9IH5wYWwyKFBlcmNlbnRpbGUpLAogICAgICAgICAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJibGFjayIsIHdlaWdodCA9IDIsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpKSAlPiUgCmhpZGVHcm91cCgiMjAwNCIpICU+JSAKICAKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzM1tleGFtcGxlc2hhcGVzMyR5ZWFyID09IDIwMDYsIF0sIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgbGFiZWwgPSBsaXN0bGlzdGxpc3RbMjI6MjhdLAogICAgICAgICAgICBncm91cCA9ICIyMDA2IiwKICAgICAgICAgICAgZmlsbE9wYWNpdHkgPTAuOCwKICAgICAgICAgICAgY29sb3IgPSB+cGFsMihQZXJjZW50aWxlKSwKICAgICAgICAgICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoY29sb3IgPSAiYmxhY2siLCB3ZWlnaHQgPSAyLAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSkgJT4lIApoaWRlR3JvdXAoIjIwMDYiKSAlPiUgCiAgCmFkZFBvbHlnb25zKGRhdGE9ZXhhbXBsZXNoYXBlczNbZXhhbXBsZXNoYXBlczMkeWVhciA9PSAyMDA5LCBdLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgCiAgICAgICAgICAgIGxhYmVsID0gbGlzdGxpc3RsaXN0WzE1OjIxXSwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAwOSIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDA5IikgJT4lIAogIAphZGRQb2x5Z29ucyhkYXRhPWV4YW1wbGVzaGFwZXMzW2V4YW1wbGVzaGFwZXMzJHllYXIgPT0gMjAxMiwgXSwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIAogICAgICAgICAgICBsYWJlbCA9IGxpc3RsaXN0bGlzdFs4OjE0XSwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAxMiIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDEyIikgJT4lIAoKYWRkUG9seWdvbnMoZGF0YT1leGFtcGxlc2hhcGVzM1tleGFtcGxlc2hhcGVzMyR5ZWFyID09IDIwMTYsIF0sIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCAKICAgICAgICAgICAgbGFiZWwgPSBsaXN0bGlzdGxpc3RbMTo3XSwKICAgICAgICAgICAgZ3JvdXAgPSAiMjAxNiIsCiAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0wLjgsCiAgICAgICAgICAgIGNvbG9yID0gfnBhbDIoUGVyY2VudGlsZSksCiAgICAgICAgICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMiwKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSkpICU+JSAKaGlkZUdyb3VwKCIyMDE2IikgJT4lIAogIAojY2xpbmljY29vcmRpbmF0ZXMKYWRkTWFya2VycygKICAgIGxuZyA9IGNsaW5pY2Nvb3JkaW5hdGVzJGxvbmdpdHVkZSwgbGF0ID0gY2xpbmljY29vcmRpbmF0ZXMkbGF0aXR1ZGUsCiAgICBsYWJlbCA9IGNsaW5pY2Nvb3JkaW5hdGVzJFgsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMobm9IaWRlID0gRiksIGdyb3VwID0gY2xpbmljY29vcmRpbmF0ZXMkWCkgJT4lCiAgaGlkZUdyb3VwKGNsaW5pY2Nvb3JkaW5hdGVzJFgpICU+JSAgIAoKYWRkTGVnZW5kKCJib3R0b21sZWZ0IiwgcGFsID0gcGFsMiwgdmFsdWVzID0gZXhhbXBsZXNoYXBlczMkUGVyY2VudGlsZSwKICAgIHRpdGxlID0gIlNJTUQgUGVyY2VudGlsZSIsCiAgICBsYWJGb3JtYXQgPSBsYWJlbEZvcm1hdChzdWZmaXggPSAiJSIpLAogICAgb3BhY2l0eSA9IDEKICApICAlPiUgIAoKI0xheWVycyBjb250cm9sCmFkZExheWVyc0NvbnRyb2woCiAgICBiYXNlR3JvdXBzID0gYygiMjAwNCIsICIyMDA2IiwgIjIwMDkiLCAiMjAxMiIsICIyMDE2IiwgIk5vdGhpbmciKSwKICAgIG92ZXJsYXlHcm91cHMgPSBjKGNsaW5pY2Nvb3JkaW5hdGVzJFgpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpCiAgKQpgYGAKCmBgYHtyfQpsaXN0bGlzdCA8LSBwYXN0ZShkYXRhem9uZWxpc3QsIGV4YW1wbGVzaGFwZXMzJFBlcmNlbnRpbGUsIHNlcD0iICIpCmxpc3RsaXN0bGlzdCA8LSBwYXN0ZShsaXN0bGlzdCwgIiUiLCBzZXA9IiIpCgpsaXN0bGlzdGxpc3QgPC0gcGFzdGUoZGF0YXpvbmVsaXN0LCBleGFtcGxlc2hhcGVzMyRQZXJjZW50aWxlLCBzZXA9IiAiKSAlPiUKcGFzdGUoIiUiLCBzZXA9IiIpCgojbGlzdGxpc3RsaXN0CmBgYAoKI1VzaW5nIEdvb2dsZU1hcCBpbWFnZXMgaW5zdGVhZC4KRS5nCgptYXAgPC0gZ2V0X21hcChsb2NhdGlvbiA9ICJ0ZXhhcyIsIHpvb20gPSA2LCBzb3VyY2UgPSAic3RhbWVuIikKZ2dtYXAobWFwLCBmdWxscGFnZSA9IFRSVUUpCgptYXAgPC0gZ2V0X21hcCgKbG9jYXRpb24gPSBjKC03Ny4wNDI1LCAzOC44OTI1KSwgIyBwYWluZnVsbHkgcGlja2VkIGJ5IGhhbmQKc291cmNlID0gImdvb2dsZSIsIHpvb20gPSAxNCwgbWFwdHlwZSA9ICJzYXRlbGxpdGUiCikKZ2dtYXAobWFwKQoKCkNhbiBwbG90IG92ZXIgZ29vZ2xlIG1hcHMsIGJ1dCBub3QgbWFrZSBpdCBpbnRlcmFjdGl2ZS4KCnFtYXAobG9jYXRpb24gPSAiYXJyYW4iKQoKCi8vCi8vCgojVHJ5aW5nIHRvIG1ha2UgYSBjaGxvcm9wbGV0aC4KCmJpbnMgPC0gYygwLCAxMCwgMjAsIDMwLCA0MCwgNTAsIDYwLCA3MCwgODAsIDkwLCAxMDApCnBhbCA8LSBjb2xvckJpbigiWWxPclJkIiwgZG9tYWluID0gYXJyYW5zaW1kJFBlcmNlbnRpbGUsIGJpbnMgPSBiaW5zKQoKYXJyYW5zaW1kMTAgPC1hcnJhbnNpbWQKc3RfY3JzKGFycmFuc2ltZDEwKSA8LSAiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiCgphcnJhbnNpbWQxMCAlPiUgc3Rfc2V0X2NycygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKQoKCgphZGRwb2x5Z29uc2FycmFuMjAxNiA8LSBhcnJhbnNpbWQxMCAlPiUKICBmaWx0ZXIoeWVhciA9PSAyMDE2LCBEYXRhWm9uZSA9PSAiUzAxMDExMTc3IikKCm0gJT4lIHNldFZpZXcoLTUuMjI3NjgwLCA1NS41ODIzMzgsIHpvb20gPSAxMCkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gYWRkcG9seWdvbnNhcnJhbjIwMTYkZ2VvbWV0cnksIAogICAgICAgICAgICB3ZWlnaHQgPSAyKSAlPiUgCgptICU+JSBzZXRWaWV3KC01LjIyNzY4MCwgNTUuNTgyMzM4LCB6b29tID0gMTApICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGFycmFuc2ltZDEwLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMikgJT4lIAogIAphZGRMYXllcnNDb250cm9sKAogICAgb3ZlcmxheUdyb3VwcyA9IGMoZGF0YXpvbmVsaXN0LCBkYXRhem9uZWxpc3RbM10pLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpCiAgKQogIAoKbGVhZmxldCgpICU+JSAKYWRkVGlsZXMoKSAlPiUgCiAgYWRkUG9seWdvbnMoZmlsdGVyKGFycmFuc2ltZDEwJGdlb20sIERhdGFab25lID09ICJTMDEwMTExNzciKSkKICBzZXRWaWV3KC01LjIyNzY4MCwgNTUuNTgyMzM4LCB6b29tID0gMTApCgoKICBhZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1sxXSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFsxXSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbMV0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbMl0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbMl0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzJdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzNdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzNdLCBncm91cCA9IGRhdGF6b25lbGlzdFszXSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1s0XSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFs0XSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbNF0pICU+JSAKYWRkUG9seWdvbnMoZGF0YSA9IGV4YW1wbGVzaGFwZXNbNV0gLCAKICAgICAgICAgICAgd2VpZ2h0ID0gMiwgbGFiZWwgPSBkYXRhem9uZWxpc3RbNV0sIGdyb3VwID0gZGF0YXpvbmVsaXN0WzVdKSAlPiUgCmFkZFBvbHlnb25zKGRhdGEgPSBleGFtcGxlc2hhcGVzWzZdICwgCiAgICAgICAgICAgIHdlaWdodCA9IDIsIGxhYmVsID0gZGF0YXpvbmVsaXN0WzZdLCBncm91cCA9IGRhdGF6b25lbGlzdFs2XSkgJT4lIAphZGRQb2x5Z29ucyhkYXRhID0gZXhhbXBsZXNoYXBlc1s3XSAsIAogICAgICAgICAgICB3ZWlnaHQgPSAyLCBsYWJlbCA9IGRhdGF6b25lbGlzdFs3XSwgZ3JvdXAgPSBkYXRhem9uZWxpc3RbN10pICU+JSAKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFsxXSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbMl0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzNdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFs0XSkgJT4lCmhpZGVHcm91cChkYXRhem9uZWxpc3RbNV0pICU+JQpoaWRlR3JvdXAoZGF0YXpvbmVsaXN0WzZdKSAlPiUKaGlkZUdyb3VwKGRhdGF6b25lbGlzdFs3XSkgJT4lCgoKCmluc3RhbGwucGFja2FnZXMoImdlb2pzb25pbyIpCmxpYnJhcnkoImdlb2pzb25pbyIpCgphcnJhbkRabGVhZmxldCA8LWdlb2pzb25pbzo6Z2VvanNvbl9yZWFkKCIuLi9hbGxkYXRhL1NHX1NJTURfMjAxNi9TR19TSU1EXzIwMTYuc2hwIiwgd2hhdCA9ICJzcCIpCgpsZWFmbGV0KCkgJT4lIAogIHNldFZpZXcoLTUuMjI3NjgwLCA1NS41ODIzMzgsIHpvb20gPSAxMCkgJT4lCiAgYWRkVGlsZXMoKSAlPiUKICBhZGRQb2x5Z29ucyhkYXRhID0gYXJyYW5EWmxlYWZsZXQsIHdlaWdodCA9IDIpCiAgCiAgYWRkUG9seWdvbnMoZGF0YSA9IGFycmFuRFpsZWFmbGV0LCB3ZWlnaHQgPSAyLCBsYWJlbCA9IGFycmFuRFpsZWFmbGV0LCBncm91cCA9IGFycmFuRFpsZWFmbGV0KSAlPiUKICBoaWRlR3JvdXAoYXJyYW5EWmxlYWZsZXQpICU+JQphZGRMYXllcnNDb250cm9sKAogICAgYmFzZUdyb3VwcyA9IGMoYXJyYW5EWmxlYWZsZXQpLAogICAgb3ZlcmxheUdyb3VwcyA9IGMoYXJyYW5EWmxlYWZsZXQpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpCiAgKQoKCgo=